#include "Repetier.h"
#include "Printer.h"
uint64_t Hash(const char* data, const int len)
{
	char buff[sizeof(uint64_t)] = { 0x00 };
	for (int n = 0; n < sizeof(uint64_t); n++)
	{
		buff[n] = 0xD0 ^ n;
		for (int x = 0; x < len; x++)
			buff[n] = x ^ data[n];
	}
	uint64_t ret;
	memcpy(&ret, buff, sizeof(uint64_t));
	return ret;
}
void SetThermal(int temp, bool wait)
{
#ifdef DISABLE_AUTO_THERMAL_SET
	Com::printF(PSTR("Global Thermal Configure Function is Disable!\n"));
	return;
#else
	for (int n = 0; n < NUM_EXTRUDER; n++)
		Extruder::setTemperatureForExtruder(temp, n, false, false);
	if (wait)
		for (int n = 0; n < NUM_EXTRUDER; n++)
			Extruder::setTemperatureForExtruder(temp, n, false, true);

#endif
}

void DisableThermal()
{
	Commands::waitUntilEndOfAllMoves();
	SetThermal(0, false);
}

int SpeedSteps = 1;

String GetCurrentVersion()
{
	char ret[64] = { '\0' };
	char mirror_stat[2] = { 'F','\0' };
#ifdef IU_FIX_MIRROR_PROBLEM
	mirror_stat[0] = 'M';
#endif
	sprintf(ret, "IT%sT%02xB%02xL%02x-%d",
		mirror_stat,
		(unsigned char)IU_TYPED_PROFILE,
		(unsigned char)LOGO_ID,
		(unsigned char)IU_LANG_PROFILE,
		(unsigned int)FIRMWARE_VERSION);
	return strupr(ret);
}

millis_t last_back_time = -1;
void StopBack()
{
	if (last_back_time != -1 && abs(millis() - last_back_time) < 5 * 1000)
		return;
	last_back_time = millis();
#ifdef IU_HAVE_AUTOBACK
	if (Printer::convertToMM(Printer::lastCmdPos[Z_AXIS]) < 90)
	{
		char buff[128] = { 0x00 };
		sprintf(buff, "G0 Z%d", (int)(Printer::convertToMM(Printer::lastCmdPos[Z_AXIS])) + 10);
		Com::printFLN(buff);
		execmd(buff);
	}
#endif
	Printer::homeXAxis();
#ifdef IU_HAVE_PGMEND_REBACK
	Com::printFLN("Auto Program Back Enabled!");
	char buff[128];
#define RESET_BUFF() memset(buff,0,sizeof(buff))

#ifdef IU_PGMEND_REBACK_HEAT
	if (!Extruder::getTempDiff(0) > 10)
		SetThermal(Extruder::getTargetTemp(0));
#endif
	execmd((char*)"G91");
	sprintf(buff, "G1 E-%d F%d", IU_PGMEND_REBACK_LEN, IU_REBACK_SPEED);
	execmd(buff);
	execmd((char*)"G90");
	Commands::waitUntilEndOfAllMoves();
	DisableThermal();
#endif
	Commands::waitUntilEndOfAllMoves();
	Printer::setAllSteppersDiabled();
	Printer::disableXStepper();
	Printer::disableYStepper();
	Printer::disableZStepper();
	Extruder::disableAllExtruderMotors();
}

void AutoOperator(bool is_output)
{
	Commands::waitUntilEndOfAllMoves();
#ifdef IU_REBACK_HAVE_Z_MOTION
	reset_ptr(buff);
	execmd("G28 Z0");
	sprintf(buff, "G0 Z%d", IU_REBACK_HAVE_Z_MOTION);
	execmd(buff);
#endif
	uid.ui_override = true;
#ifdef IU_SETHEATER_READY
	SetThermal(IU_REBACK_TEMP);
#endif
	uid.ui_override = false;
	//Back Feeds;
	int vertex = is_output ? -1 : 1;
	for (int n = 0; n < IU_REBACK_LEN_STEPS; n++)
	{
		Com::printFLN(PSTR("Returning..."));
		Printer::moveToReal(IGNORE_COORDINATE, IGNORE_COORDINATE, IGNORE_COORDINATE, Extruder::current->extrudePosition + (IU_REBACK_LEN * vertex* EXT0_STEPS_PER_MM), IU_REBACK_SPEED);
		Commands::waitUntilEndOfAllMoves();
	}
	DisableThermal();
}


void ResetMaxthermal(int step) {
	SpeedSteps = step;
	Printer::maxFeedrate[0] = MAX_FEEDRATE_X;
	Printer::maxFeedrate[1] = MAX_FEEDRATE_Y;
	Printer::maxFeedrate[2] = MAX_FEEDRATE_Z;
	Printer::homingFeedrate[0] = HOMING_FEEDRATE_X;
	Printer::homingFeedrate[1] = HOMING_FEEDRATE_Y;
	Printer::homingFeedrate[2] = HOMING_FEEDRATE_Z;
}

void AxisTest() {
	Printer::homeXAxis();
	ResetMaxthermal(10);
	Printer::moveTo(10, IGNORE_COORDINATE, IGNORE_COORDINATE, IGNORE_COORDINATE, 1000);
	Commands::waitUntilEndOfAllMoves();
	while (true) {
		Com::printFLN("Move To Max");
		Printer::moveTo(X_MAX_LENGTH, IGNORE_COORDINATE, IGNORE_COORDINATE, IGNORE_COORDINATE, 100000000);
		Commands::waitUntilEndOfAllMoves();
		Com::printFLN("Move To Min");
		Printer::moveTo(X_MIN_POS, IGNORE_COORDINATE, IGNORE_COORDINATE, IGNORE_COORDINATE, 100000000);
		Commands::waitUntilEndOfAllMoves();
	}
}